/*
@author: ZZH
@date: 2021-11-05
@time: 14:19:17
@info: 内存管理实现
*/
#include "MemMana.h"
#include "stdio.h"
#include "operations.h"

static uint8_t __mem0__[409600];

MemPool_t __MemPools__[] = {
    ArrayMem(__mem0__),
};

void __init ZMemInit()
{
    printf("init Mem Pool\r\n");
    EACH(__MemPools__) //initial all mem pool
    {
        pMemBlock_t pMemHeader = pMember->memStart;
        pMember->availableSize = (size_t) pMember->memEnd - (size_t) pMember->memStart;
        pMemHeader->isFree = true;
        pMemHeader->prev = nullptr;
        pMemHeader->next = nullptr;
        pMemHeader->size = pMember->availableSize;
    }
}

void* ZMalloc(const uint32_t pool, size_t size)
{
    if (size == 0)
        return NULL;

    pMemBlock_t pMemHeader = __MemPools__[pool].memStart;
    //字节对齐操作
    size = (size + 0x0000003) & ~0x00000003;
    size += sizeof(MemBlock_t);
    size_t sizeReq = size + sizeof(MemBlock_t);//分配一个内存块最小需要的大小
    while (pMemHeader != NULL)
    {
        if (pMemHeader->isFree && pMemHeader->size > sizeReq)//必须大于,否则后面的内存块相当于只有内存头
        {
            pMemBlock_t newHeader = (pMemBlock_t) ((char*) pMemHeader + size);//在分配出去的内存块后面建立一个新的内存块
            newHeader->isFree = true;
            newHeader->size = pMemHeader->size - sizeReq;
            newHeader->prev = pMemHeader;
            newHeader->next = NULL;

            pMemHeader->next = newHeader;
            pMemHeader->size = sizeReq;
            pMemHeader->isFree = false;

            __MemPools__[pool].availableSize -= sizeReq;

            return (char*) pMemHeader->mem;
        }
        else
        {
            pMemHeader = pMemHeader->next;
        }
    }
    return NULL;
}

void ZFree(void* pMem)
{
    pMemBlock_t block = container_of(pMem, MemBlock_t, mem);

    if(block == NULL || block->isFree)
        return;

    pMemPool_t pool = NULL;

    EACH(__MemPools__)
    {
        if (pMem < (void*)pMember->memEnd && pMem > (void*)pMember->memStart)
            pool = pMember;
    }

    if(pool == NULL)
        return;
    
    pool->availableSize += block->size;

    block->isFree = true;

    pMemBlock_t prev = block->prev, next = block->next;

    if (next && next->isFree)
    {
        block->size += next->size;
        block->next = next->next;
        if (next->next)
            next->next->prev = block;
    }

    if (prev && prev->isFree)
    {
        prev->size += block->size;
        prev->next = block->next;
        if (block->next)
            block->next->prev = prev;
    }
}